/*
 * Copyright (c) 2002-2003 by OpenSymphony
 * All rights reserved.
 */
package org.jackysoft.opensymphony.workflow.entity;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.jackysoft.util.ValidationUtils;

import com.google.common.collect.Lists;

/**
 * @author <a href="mailto:plightbo@hotmail.com">Pat Lightbody</a>
 */

public class ActionDescriptor extends AbstractDescriptor implements Validatable {
	// ~ Instance fields
	// ////////////////////////////////////////////////////////

	/**
	 * 
	 */
	private static final long serialVersionUID = -8537494292218225618L;
	protected List conditionalResults = new ArrayList();
	protected List postFunctions = new ArrayList();
	protected List preFunctions = new ArrayList();
	protected List validators = new ArrayList();
	protected Map metaAttributes = new HashMap();
	protected RestrictionDescriptor restriction;
	protected ResultDescriptor unconditionalResult;
	protected String name;
	protected String view;
	protected boolean autoExecute = false;
	protected boolean common;
	protected boolean finish = false;


	
	// ~ Methods
	// ////////////////////////////////////////////////////////////////

	public ActionDescriptor(){
		     
	}
	public ActionDescriptor(org.dom4j.Element adc) {		
		super(adc);
		this.init(element);
	}

	public void setAutoExecute(boolean autoExecute) {
		this.autoExecute = autoExecute;
	}

	public boolean getAutoExecute() {
		return autoExecute;
	}

	public boolean isCommon() {
		return common;
	}

	public List getConditionalResults() {
		return conditionalResults;
	}

	public void setFinish(boolean finish) {
		this.finish = finish;
	}

	public boolean isFinish() {

		return finish;

	}

	public void setMetaAttributes(Map metaAttributes) {
		this.metaAttributes = metaAttributes;
	}

	public Map getMetaAttributes() {
		return metaAttributes;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getName() {
		return name;
	}

	public List getPostFunctions() {
		return postFunctions;
	}

	public List getPreFunctions() {
		return preFunctions;
	}

	public void setRestriction(RestrictionDescriptor restriction) {
		this.restriction = restriction;
	}

	public RestrictionDescriptor getRestriction() {
		return restriction;
	}

	public void setUnconditionalResult(ResultDescriptor unconditionalResult) {
		this.unconditionalResult = unconditionalResult;
	}

	public ResultDescriptor getUnconditionalResult() {
		return unconditionalResult;
	}

	public List getValidators() {
		return validators;
	}

	public void setView(String view) {
		this.view = view;
	}

	public String getView() {
		return view;
	}

	public String toString() {
		StringBuffer sb = new StringBuffer();

		if (name != null) {
			sb.append(name);
		}

		if ((view != null) && (view.length() > 0)) {
			sb.append(" (").append(view).append(")");
		}

		return sb.toString();
	}

	public void validate() throws InvalidWorkflowDescriptorException {
		ValidationUtils.validate(preFunctions);
		ValidationUtils.validate(postFunctions);
		ValidationUtils.validate(validators);
		ValidationUtils.validate(conditionalResults);

		if ((conditionalResults.size() > 0) && (unconditionalResult == null)) {
			throw new InvalidWorkflowDescriptorException(
					"Action "
							+ name
							+ " has conditional results but no fallback unconditional result");
		}

		if (restriction != null) {
			restriction.validate();
		}

		if (unconditionalResult != null) {
			unconditionalResult.validate();
		}
	}

	@Override
	protected void init(org.dom4j.Element action) {
		conditionalResults = new ArrayList();
		postFunctions = new ArrayList();     
		preFunctions = new ArrayList();      
		validators = new ArrayList();   
		try {
			setId(Integer.parseInt(action.attributeValue("id")));
		} catch (Exception ex) {
			throw new IllegalArgumentException("Invalid action id value '"
					+ action.attributeValue("id") + "'");
		}

		this.name = action.attributeValue("name");
		this.view = action.attributeValue("view");
		this.autoExecute = "true".equalsIgnoreCase(action
				.attributeValue("auto"));
		this.finish = "true".equalsIgnoreCase(action.attributeValue("finish"));

		for (Iterator itr = action.elementIterator(); itr.hasNext();) {
			org.dom4j.Element child = (org.dom4j.Element) itr.next();
			String nodeName = child.getQName().getName();
			if ("validators".equals(nodeName)) {
				buildElements(child, "validator", ValidatorDescriptor.class,
						this.validators, this);
			}

			if ("pre-functions".equals(nodeName)) {
				buildElements(child, "function", FunctionDescriptor.class,
						this.preFunctions, this);

			}

			if ("results".equals(nodeName)) {    
				
				buildElements(child, "result",ConditionalResultDescriptor.class,this.conditionalResults, this);
				org.dom4j.Element unconditionalResult = child
						.element("unconditional-result");
				if (unconditionalResult != null) {
					this.unconditionalResult = new ResultDescriptor(
							unconditionalResult);
					this.unconditionalResult.setParent(this);
				}
			}

			if ("post-functions".equals(nodeName)) {
				buildElements(child, "function", FunctionDescriptor.class,
						this.postFunctions, this);
			}

			if ("restrict-to".equals(nodeName)) {
				restriction = new RestrictionDescriptor(child);
				if (restriction.getConditionsDescriptor() == null) {
					restriction = null;
				} else {
					restriction.setParent(this);
				}
			}
		}

	}

	
	void setCommon(boolean common) {
		this.common = common;
	}
}
